package org.ysling.litemall.db.service;
// Copyright (c) [ysling] [927069313@qq.com]
// [litemall-plus] is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//             http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
import com.github.pagehelper.PageHelper;
import org.springframework.util.StringUtils;
import org.ysling.litemall.db.constant.RandomStrUtil;
import org.ysling.litemall.db.dao.LitemallCouponMapper;
import org.ysling.litemall.db.dao.LitemallCouponUserMapper;
import org.ysling.litemall.db.domain.LitemallCoupon;
import org.ysling.litemall.db.domain.LitemallCoupon.Column;
import org.ysling.litemall.db.domain.LitemallCouponUser;
import org.ysling.litemall.db.example.LitemallCouponExample;
import org.ysling.litemall.db.example.LitemallCouponUserExample;
import org.ysling.litemall.db.constant.CouponConstant;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
@CacheConfig(cacheNames = "coupon")
public class LitemallCouponService {
    
    @Resource
    private LitemallCouponMapper couponMapper;
    @Resource
    private LitemallCouponUserMapper couponUserMapper;

    private Column[] result = new Column[]{Column.id, Column.name, Column.desc, Column.tag,
                                            Column.days, Column.startTime, Column.endTime,
                                            Column.discount, Column.min, Column.version};

    /**
     * 查询，空参数
     *
     * @param offset
     * @param limit
     * @param sort
     * @param order
     * @return
     */
    @Cacheable(sync = true)
    public List<LitemallCoupon> queryList(int offset, int limit, String sort, String order) {
        return queryList(LitemallCouponExample.newAndCreateCriteria(), offset, limit, sort, order);
    }

    /**
     * 查询
     *
     * @param criteria 可扩展的条件
     * @param offset
     * @param limit
     * @param sort
     * @param order
     * @return
     */
    @Cacheable(sync = true)
    public List<LitemallCoupon> queryList(LitemallCouponExample.Criteria criteria, int offset, int limit, String sort, String order) {
        criteria.andTypeEqualTo(CouponConstant.TYPE_COMMON)
                .andStatusEqualTo(CouponConstant.STATUS_NORMAL)
                .andDeletedEqualTo(false);
        criteria.example().setOrderByClause(sort + " " + order);
        PageHelper.startPage(offset, limit);
        return couponMapper.selectByExampleSelective(criteria.example(), result);
    }

    @Cacheable(sync = true)
    public List<LitemallCoupon> queryAvailableList(Integer userId, int offset, int limit) {
        if (userId == null) return queryList(0, 3);
        // 过滤掉登录账号已经领取过的coupon
        LitemallCouponExample.Criteria c = LitemallCouponExample.newAndCreateCriteria();
        List<LitemallCouponUser> used = couponUserMapper.selectByExample(
                LitemallCouponUserExample.newAndCreateCriteria().andUserIdEqualTo(userId).example()
        );
        if(used!=null && !used.isEmpty()){
            c.andIdNotIn(used.stream().map(LitemallCouponUser::getCouponId).collect(Collectors.toList()));
        }
        return queryList(c, offset, limit, "add_time", "desc");
    }

    @Cacheable(sync = true)
    public List<LitemallCoupon> queryList(int offset, int limit) {
        return queryList(offset, limit, "add_time", "desc");
    }

    @Cacheable(sync = true)
    public LitemallCoupon findById(Integer id) {
        return couponMapper.selectByPrimaryKey(id);
    }


    @Cacheable(sync = true)
    public LitemallCoupon findByCode(String code) {
        LitemallCouponExample example = new LitemallCouponExample();
        example.or().andCodeEqualTo(code)
                .andTypeEqualTo(CouponConstant.TYPE_CODE)
                .andStatusEqualTo(CouponConstant.STATUS_NORMAL)
                .andDeletedEqualTo(false);

        List<LitemallCoupon> couponList =  couponMapper.selectByExample(example);

        if(couponList.size() > 1){
            throw new RuntimeException("");
        }
        else if(couponList.size() == 0){
            return null;
        }
        else {
            return couponList.get(0);
        }
    }

    /**
     * 查询新用户注册优惠券
     *
     * @return
     */
    @Cacheable(sync = true)
    public List<LitemallCoupon> queryRegister() {
        LitemallCouponExample example = new LitemallCouponExample();
        example.or()
                .andTypeEqualTo(CouponConstant.TYPE_REGISTER)
                .andStatusEqualTo(CouponConstant.STATUS_NORMAL)
                .andDeletedEqualTo(false);
        return couponMapper.selectByExample(example);
    }

    @Cacheable(sync = true)
    public List<LitemallCoupon> querySelective(String name, Short type, Short status, Integer page, Integer limit, String sort, String order) {
        LitemallCouponExample example = new LitemallCouponExample();
        LitemallCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);

        if (type != null) {
            criteria.andTypeEqualTo(type);
        }
        if (status != null) {
            criteria.andStatusEqualTo(status);
        }
        if (StringUtils.hasText(name)) {
            criteria.andNameLike("%" + name + "%");
        }
        if (StringUtils.hasText(sort) && StringUtils.hasText(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, limit);
        return couponMapper.selectByExample(example);
    }

    @CacheEvict(allEntries = true)
    public void add(LitemallCoupon coupon) {
        coupon.setAddTime(LocalDateTime.now());
        coupon.setUpdateTime(LocalDateTime.now());
        couponMapper.insertSelective(coupon);
    }

    @CacheEvict(allEntries = true)
    public int updateById(LitemallCoupon coupon) {
        coupon.setUpdateTime(LocalDateTime.now());
        return couponMapper.updateByPrimaryKeySelective(coupon);
    }

    @CacheEvict(allEntries = true)
    public int updateVersionSelective(LitemallCoupon coupon) {
        coupon.setUpdateTime(LocalDateTime.now());
        return couponMapper.updateWithVersionByPrimaryKeySelective(coupon.getVersion(), coupon);
    }

    @CacheEvict(allEntries = true)
    public void deleteById(Integer id) {
        couponMapper.logicalDeleteByPrimaryKey(id);
    }


    /**
     * 生成优惠码
     *
     * @return 可使用优惠码
     */
    public String generateCode() {
        String code = RandomStrUtil.getRandom(8, RandomStrUtil.TYPE.CAPITAL_NUMBER);
        while(findByCode(code) != null){
            code = RandomStrUtil.getRandom(8, RandomStrUtil.TYPE.CAPITAL_NUMBER);
        }
        return code;
    }

    /**
     * 查询过期的优惠券:
     * 注意：如果timeType=0, 即基于领取时间有效期的优惠券，则优惠券不会过期
     *
     * @return
     */
    @Cacheable(sync = true)
    public List<LitemallCoupon> queryExpired() {
        LitemallCouponExample example = new LitemallCouponExample();
        example.or().andStatusEqualTo(CouponConstant.STATUS_NORMAL)
                .andTimeTypeEqualTo(CouponConstant.TIME_TYPE_TIME)
                .andEndTimeLessThan(LocalDateTime.now())
                .andDeletedEqualTo(false);
        return couponMapper.selectByExample(example);
    }
}
